{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 枚举的定义\n",
    "- 1.首先枚举要导入enum模块，实现代码：from Enum import enum\n",
    "- 2.枚举定义用class关键字，继承Enum类\n",
    "- 3.用于定义枚举的class和定义类的class是有区别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from enum import Enum\n",
    "class Color (Enum):\n",
    "      red=1\n",
    "      orange=2\n",
    "      yellow=3\n",
    "      green=4\n",
    "      blue=5\n",
    "      indigo=6\n",
    "      purple=7"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 代码分析：\n",
    "- 1.上面的代码，我们定义了颜色的枚举Color\n",
    "- 2.颜色枚举有7个成员，分别是Color.red、Color.orange、Color.yellow等\n",
    "- 3.每一个成员都有它们各自名称和值，Color.red成员的名称是：red，值是：1\n",
    "- 4.每个成员的数据类型就是它所属的枚举"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 枚举取值\n",
    "## 通过成员的名称来获取成员"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Color.red: 1>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Color['red']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过成员值来获取成员"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Color.orange: 2>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Color(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过成员，来获取它的名称和值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "red\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "red_member = Color.red\n",
    "print(red_member.name)\n",
    "print(red_member.value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 迭代器\n",
    "## 枚举支持迭代器，可以遍历枚举成员"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Color.red\n",
      "Color.orange\n",
      "Color.yellow\n",
      "Color.green\n",
      "Color.blue\n",
      "Color.indigo\n",
      "Color.purple\n"
     ]
    }
   ],
   "source": [
    "for color in Color:\n",
    "    print(color)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 如果枚举有值重复的成员，循环遍历枚举时只获取值重复成员的第一个成员"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Color.red\n",
      "Color.orange\n",
      "Color.yellow\n",
      "Color.green\n",
      "Color.blue\n",
      "Color.indigo\n",
      "Color.purple\n"
     ]
    }
   ],
   "source": [
    "from enum import Enum\n",
    "\n",
    "class Color(Enum):\n",
    "    red = 1\n",
    "    orange = 2\n",
    "    yellow = 3\n",
    "    green = 4\n",
    "    blue = 5\n",
    "    indigo = 6\n",
    "    purple = 7\n",
    "    red_alias = 1\n",
    "\n",
    "for color in Color:\n",
    "    print(color)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 如果想把值重复的成员也遍历出来，要用枚举的一个特殊属性`_members_`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('red', <Color.red: 1>)\n",
      "('orange', <Color.orange: 2>)\n",
      "('yellow', <Color.yellow: 3>)\n",
      "('green', <Color.green: 4>)\n",
      "('blue', <Color.blue: 5>)\n",
      "('indigo', <Color.indigo: 6>)\n",
      "('purple', <Color.purple: 7>)\n",
      "('red_alias', <Color.red: 1>)\n"
     ]
    }
   ],
   "source": [
    "from enum import Enum\n",
    "\n",
    "class Color(Enum):\n",
    "    red = 1\n",
    "    orange = 2\n",
    "    yellow = 3\n",
    "    green = 4\n",
    "    blue = 5\n",
    "    indigo = 6\n",
    "    purple = 7\n",
    "    red_alias = 1\n",
    "\n",
    "for color in Color.__members__.items():\n",
    "    print(color)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 枚举常见问题\n",
    "##  定义枚举时，成员名称不允许重复"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "Attempted to reuse key: 'red'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-12-28b9e8016bc5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0menum\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mEnum\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32mclass\u001b[0m \u001b[0mColor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mEnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m        \u001b[0mred\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m        \u001b[0mred\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-12-28b9e8016bc5>\u001b[0m in \u001b[0;36mColor\u001b[0;34m()\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mColor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mEnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m        \u001b[0mred\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m        \u001b[0mred\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/anaconda3/lib/python3.7/enum.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m     99\u001b[0m         \u001b[0;32melif\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_member_names\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    100\u001b[0m             \u001b[0;31m# descriptor overwriting an enum?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 101\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Attempted to reuse key: %r'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    102\u001b[0m         \u001b[0;32melif\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_ignore\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    103\u001b[0m             \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: Attempted to reuse key: 'red'"
     ]
    }
   ],
   "source": [
    "from enum import Enum\n",
    "class Color(Enum):\n",
    "       red=1\n",
    "       red=2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上述代码会出现错误，无法执行。提示错误：`TypeError: Attempted to reuse key: ‘red’`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 默认情况下，不同的成员值允许相同。但是两个相同值的成员，第二个成员的名称被视作第一个成员的别名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from enum import Enum\n",
    "class Color(Enum):\n",
    "       red=1\n",
    "       red_alias=1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "成员`Color.red`和`Color.red_alias`具有相同的值，那么成员`Color.red_alias`的名称`red_alias`就被视作成员`Color.red`名称`red`的别名。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 如果枚举中存在相同值的成员，在通过值获取枚举成员时，只能获取到第一个成员"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Color.red\n"
     ]
    }
   ],
   "source": [
    "from enum import Enum\n",
    "\n",
    "class Color(Enum):\n",
    "    red = 1\n",
    "    red_alias = 1\n",
    "\n",
    "print(Color(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 如果要限制定义枚举时，不能定义相同值的成员。可以使用装饰器`@unique`【要导入unique模块】"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "duplicate values found in <enum 'Color'>: red_alias -> red",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-16-f119d87b1fca>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0munique\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mclass\u001b[0m \u001b[0mColor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mEnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m     \u001b[0mred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m     \u001b[0mred_alias\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/enum.py\u001b[0m in \u001b[0;36munique\u001b[0;34m(enumeration)\u001b[0m\n\u001b[1;32m    867\u001b[0m                 [\"%s -> %s\" % (alias, name) for (alias, name) in duplicates])\n\u001b[1;32m    868\u001b[0m         raise ValueError('duplicate values found in %r: %s' %\n\u001b[0;32m--> 869\u001b[0;31m                 (enumeration, alias_details))\n\u001b[0m\u001b[1;32m    870\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0menumeration\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    871\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: duplicate values found in <enum 'Color'>: red_alias -> red"
     ]
    }
   ],
   "source": [
    "from enum import Enum, unique\n",
    "\n",
    "@unique\n",
    "class Color(Enum):\n",
    "    red = 1\n",
    "    red_alias = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
